package com.sms.client.ui;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.maps.client.InfoWindow;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.Maps;
import com.google.gwt.maps.client.event.MarkerClickHandler;
import com.google.gwt.maps.client.event.MarkerDragEndHandler;
import com.google.gwt.maps.client.geocode.Geocoder;
import com.google.gwt.maps.client.geocode.LatLngCallback;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.geom.LatLngBounds;
import com.google.gwt.maps.client.geom.Point;
import com.google.gwt.maps.client.geom.Size;
import com.google.gwt.maps.client.overlay.Icon;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.MarkerOptions;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitHandler;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.sms.client.ServiceUtil;
import com.sms.shared.SessionInfo;

public class GoogleMap extends Composite {
	private LatLng gopoint = null;
	private Geocoder geocoder;
	private static final TextBox latLabel = new TextBox();
	private static final TextBox lngLabel = new TextBox();;

	private MapWidget map;
	private HorizontalPanel horiz = new HorizontalPanel();;
	private Panel panel;
	private String menuName;
	private String sessionId;

	public GoogleMap(final String width, final String height, final String area, final Double latitude, final Double longitude, final AsyncCallback asyncCallbackMain) {
		panel = new FlowPanel();
		panel.setHeight(height);
		panel.setWidth(width);

		final FormPanel form = new FormPanel();
		form.setAction("#");

		Maps.loadMapsApi("", "2", false, new Runnable() {
			public void run() {
				if (latitude != null && longitude != null && latitude > 0.0 && longitude > 0.0) {
					gopoint = LatLng.newInstance(latitude, longitude);
				} else {
					gopoint = LatLng.newInstance(13.0810, 80.2740);
				}
				Panel formElements = new FlowPanel();
				formElements.add(horiz);

				Button submit = new Button("Find Again!");
				submit.addClickHandler(new ClickHandler() {
					public void onClick(ClickEvent event) {
						form.submit();
					}
				});
				formElements.add(submit);
				form.add(formElements);
				form.addSubmitHandler(new SubmitHandler() {
					public void onSubmit(SubmitEvent event) {
						if (area != null)
							showAddress(area, asyncCallbackMain);
						event.cancel();
					}
				});
				panel.add(form);

				if (gopoint != null) {
					map = new MapWidget(gopoint, 12);
					map.setScrollWheelZoomEnabled(true);
					map.setWidth(width);
					map.setHeight(height);
				}
				if (width != null && width.length() > 0)
					map.setWidth(width);

				if (height != null && height.length() > 0)
					map.setHeight(height);

				panel.add(map);
				HorizontalPanel horizontalPanel = new HorizontalPanel();

				horizontalPanel.add(submit);
				// horizontalPanel.add(enlargButton);
				panel.add(horizontalPanel);
				geocoder = new Geocoder();
				if (area != null)
					showAddress(area, asyncCallbackMain);
			}
		});
		initWidget(panel);

	}

	public GoogleMap(final String menuName, final Map areaMap, final String type, final String width, final String height) {
		SessionInfo userSessionInfo = SessionInfo.getSharedInstance();
		this.sessionId = (String) userSessionInfo.getSessionData(SessionInfo.JSESSION_ID);
		this.menuName = menuName;
		panel = new FlowPanel();
		final FormPanel form = new FormPanel();
		form.setAction("#");
		panel.setHeight(height);
		panel.setWidth(width);

		Maps.loadMapsApi("", "2", false, new Runnable() {
			public void run() {
				gopoint = LatLng.newInstance(13.0810, 80.2740);
				Panel formElements = new FlowPanel();
				formElements.add(horiz);

				Button submit = new Button("Find Again!");
				submit.addClickHandler(new ClickHandler() {
					public void onClick(ClickEvent event) {
						form.submit();
					}
				});

				formElements.add(submit);
				form.add(formElements);
				form.addSubmitHandler(new SubmitHandler() {
					public void onSubmit(SubmitEvent event) {
						showAddressForString(areaMap, type, width, height, new AsyncCallback() {

							@Override
							public void onFailure(Throwable caught) {
								caught.printStackTrace();
							}

							@Override
							public void onSuccess(Object result) {
								map = (MapWidget) result;
								panel.add(map);
								panel.add(form);
							}
						});
						event.cancel();
					}
				});

				HorizontalPanel horizontalPanel = new HorizontalPanel();

				horizontalPanel.add(submit);
				panel.add(horizontalPanel);
				geocoder = new Geocoder();
				showAddressForString(areaMap, type, width, height, new AsyncCallback() {

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub
					}

					@Override
					public void onSuccess(Object result) {
						if (panel.isAttached())
							panel.clear();
						map = (MapWidget) result;
						panel.add(map);
						panel.add(form);
					}
				});
			}
		});

		initWidget(panel);
	}

	// private void showAddress(String add, List area) {
	// map.setUIToDefault();
	// map.clearOverlays();
	//
	// Icon icon =
	// Icon.newInstance("http://labs.google.com/ridefinder/images/mm_20_red.png");
	// icon.setShadowURL("http://labs.google.com/ridefinder/images/mm_20_shadow.png");
	// icon.setIconSize(Size.newInstance(12, 20));
	// icon.setShadowSize(Size.newInstance(22, 20));
	// icon.setIconAnchor(Point.newInstance(6, 20));
	// icon.setInfoWindowAnchor(Point.newInstance(5, 1));
	//
	// LatLngBounds bounds = map.getBounds();
	// LatLng southWest = bounds.getSouthWest();
	// LatLng northEast = bounds.getNorthEast();
	// double lngSpan = northEast.getLongitude() - southWest.getLongitude();
	// double latSpan = northEast.getLatitude() - southWest.getLatitude();
	// MarkerOptions options = MarkerOptions.newInstance();
	// options.setIcon(icon);
	//
	// int length = area == null ? 0 : area.size();
	// for (int i = 0; i < length; i++) {
	// List latLngList = (List) area.get(i);
	// int latLnglength = latLngList == null ? 0 : latLngList.size();
	// if (latLnglength != 2) {
	// throw new RuntimeException();
	// } else {
	//
	// Double lan = Double.parseDouble(latLngList.get(0) + "");
	// Double lng = Double.parseDouble(latLngList.get(1) + "");
	// LatLng point = LatLng.newInstance(lan, lng);
	//
	// map.addOverlay(new Marker(point, options));
	// }
	//
	// }
	// }

	private void showAddressForString(Map addressMap, String type, String width, String height, final AsyncCallback asyncCallback) {
		map = new MapWidget(LatLng.newInstance(13.0810, 80.2740), 12);
		map.setSize(width, height);
		map.setUIToDefault();
		map.setUIToDefault();
		map.clearOverlays();

		final Icon icon = Icon.newInstance("http://labs.google.com/ridefinder/images/mm_20_red.png");
		icon.setShadowURL("http://labs.google.com/ridefinder/images/mm_20_shadow.png");
		icon.setIconSize(Size.newInstance(12, 20));
		icon.setShadowSize(Size.newInstance(22, 20));
		icon.setIconAnchor(Point.newInstance(6, 20));
		icon.setInfoWindowAnchor(Point.newInstance(5, 1));

		LatLngBounds bounds = map.getBounds();
		LatLng southWest = bounds.getSouthWest();
		LatLng northEast = bounds.getNorthEast();
		map.clearOverlays();
		Iterator itr = addressMap.keySet().iterator();
		while (itr.hasNext()) {
			if (type.equalsIgnoreCase("Address")) {
				final String address = (String) itr.next();
				final List meterList = (List) addressMap.get(address);
				final String meterNo = meterList.toString();
				geocoder.getLatLng(address, new LatLngCallback() {
					public void onFailure() {
						System.err.println(address + " not found");
					}

					public void onSuccess(final LatLng point) {
						final MarkerOptions options = MarkerOptions.newInstance();
						options.setIcon(icon);
						options.setTitle(address + " " + meterNo);
						final Marker marker = new Marker(point, options);
						map.setCenter(point, 4);
						map.addOverlay(marker);

						marker.addMarkerClickHandler(new MarkerClickHandler() {

							@Override
							public void onClick(MarkerClickEvent event) {
								String title = marker.getTitle();
								final String[] titleParts = title.split("\\[")[1].split("\\]");
								System.out.println(titleParts[0]);
								if (!titleParts[0].contains(",")) {
									setSession(titleParts[0].trim());
								} else {
									final VerticalPanel popupMain = new VerticalPanel();
									final VerticalPanel radioPanel = new VerticalPanel();
									String[] groupNos = titleParts[0].split(",");
									int rIndex = 0;
									for (String groupNo : groupNos) {
										RadioButton radioButton = new RadioButton("radioGroup", groupNo.trim());
										if (rIndex == 0)
											radioButton.setValue(true);
										radioPanel.add(radioButton);
										rIndex++;
									}

									popupMain.add(radioPanel);

									final HorizontalPanel buttonPanel = new HorizontalPanel();
									Button okButton = new Button("Ok");
									Button cancelButton = new Button("Cancel");
									buttonPanel.add(okButton);
									buttonPanel.add(cancelButton);
									popupMain.add(buttonPanel);

									final PopupPanel popup = new PopupPanel();
									popup.add(popupMain);
									popup.setAutoHideEnabled(false);
									popup.center();
									okButton.addClickHandler(new ClickHandler() {

										@Override
										public void onClick(ClickEvent event) {
											String sGroupNo = "";
											for (int index = 0; index < radioPanel.getWidgetCount(); index++) {
												RadioButton radioButton = (RadioButton) radioPanel.getWidget(index);
												if (radioButton.getValue()) {
													sGroupNo = radioButton.getText();
													break;
												}
											}
											popup.hide();
											setSession(sGroupNo.trim());
										}
									});
									cancelButton.addClickHandler(new ClickHandler() {

										@Override
										public void onClick(ClickEvent event) {
											popup.hide();
										}
									});
								}
							}
						});
					}

				});
			}
			// else if (type.equalsIgnoreCase("LatLng")) {
			// final MarkerOptions options = MarkerOptions.newInstance();
			// options.setIcon(icon);
			// final ArrayList valueList = (ArrayList) addressList.get(i);
			// Double latitude = (Double) valueList.get(0);
			// Double longitude = (Double) valueList.get(1);
			// LatLng point = LatLng.newInstance(latitude, longitude);
			//
			// map.setCenter(point, 4);
			// map.addOverlay(new Marker(point, options));
			//
			// }

		}
		asyncCallback.onSuccess(map);
	}

	private void setSession(final String groupNo) {
		ServiceUtil.getUserLoginServiceAsync().setSessionData(groupNo, null,sessionId, new AsyncCallback() {

			@Override
			public void onFailure(Throwable caught) {
				caught.printStackTrace();

			}

			@Override
			public void onSuccess(Object result) {
				if (result == null)
					return;
				Map resultMap = (Map) result;
				SessionInfo mUserSessionInfo = (SessionInfo) resultMap.get("result");
				SessionInfo.setUserSessionInfo(mUserSessionInfo);
				String siteId = (String) mUserSessionInfo.getSessionData(SessionInfo.SESSION_SITEID);
				String siteName = (String) mUserSessionInfo.getSessionData(SessionInfo.SESSION_SITENAME);
				RootPanel.get("mainContainer").clear();
				if (menuName.equalsIgnoreCase("Dash Board"))
					RootPanel.get("mainContainer").add(new DashBoardUI(Long.valueOf(siteId), siteName, groupNo, "Daily", "Utility"));
				if (menuName.equalsIgnoreCase("Live"))
					RootPanel.get("mainContainer").add(new LiveProductionUI(Long.valueOf(siteId), siteName, groupNo));
			}
		});

	}

	private Panel buildLatLngPanel() {
		horiz.add(new Label("Lat:"));
		horiz.add(latLabel);
		horiz.add(new Label("Long:"));
		horiz.add(lngLabel);
		horiz.setSpacing(10);
		displayLatLng();
		return horiz;
	}

	private void displayLatLng() {
		NumberFormat fmt = NumberFormat.getFormat("#.0000000#");
		latLabel.setText((fmt.format(gopoint.getLatitude())));
		lngLabel.setText(fmt.format(gopoint.getLongitude()));
		buildLatLngPanel();
		horiz.clear();
		horiz.add(new Label("Lat:"));
		horiz.add(new Label((fmt.format(gopoint.getLatitude()))));
		horiz.add(new Label("Long:"));
		horiz.add(new Label(fmt.format(gopoint.getLongitude())));
		horiz.setSpacing(10);

	}

	private void showAddress(final String address, final AsyncCallback asyncCallback) {
		final InfoWindow info = map.getInfoWindow();

		geocoder.getLatLng(address, new LatLngCallback() {
			public void onFailure() {
				System.err.println(address + " not found");
			}

			public void onSuccess(final LatLng point) {
				final MarkerOptions options = MarkerOptions.newInstance();
				options.setDraggable(true);
				map.setCenter(point, 15);
				map.setUIToDefault();

				map.setGoogleBarEnabled(false);
				gopoint = point;
				final Marker marker = new Marker(point, options);
				marker.addMarkerDragEndHandler(new MarkerDragEndHandler() {
					public void onDragEnd(MarkerDragEndEvent event) {
						gopoint = marker.getLatLng();
						info.open(marker, new InfoWindowContent(address + marker.getLatLng()));

						if (asyncCallback != null) {
							Map map = new HashMap();
							map.put("Latitude", gopoint.getLatitude());
							map.put("Longitude", gopoint.getLongitude());
							asyncCallback.onSuccess(map);
						}
					}
				});
				map.clearOverlays();
				map.addOverlay(marker);
				info.open(marker, new InfoWindowContent(address + marker.getLatLng()));
				if (asyncCallback != null) {
					Map map = new HashMap();
					map.put("Latitude", gopoint.getLatitude());
					map.put("Longitude", gopoint.getLongitude());
					asyncCallback.onSuccess(map);
				}
			}
		});
	}

	private void showAddressLanLon(final LatLng point, final String address, final AsyncCallback asyncCallback) {
		final InfoWindow info = map.getInfoWindow();
		final MarkerOptions options = MarkerOptions.newInstance();
		options.setDraggable(true);

		map.setCenter(point, 3);
		map.setUIToDefault();
		map.setGoogleBarEnabled(true);
		gopoint = point;

		final Marker marker = new Marker(point, options);
		marker.addMarkerDragEndHandler(new MarkerDragEndHandler() {
			public void onDragEnd(MarkerDragEndEvent event) {
				gopoint = marker.getLatLng();
				info.open(marker, new InfoWindowContent(address + marker.getLatLng()));

				if (asyncCallback != null) {
					Map map = new HashMap();
					map.put("Latitude", gopoint.getLatitude());
					map.put("Longitude", gopoint.getLongitude());
					asyncCallback.onSuccess(map);
				}
			}
		});
		map.clearOverlays();
		map.addOverlay(marker);
		info.open(marker, new InfoWindowContent(address + marker.getLatLng()));
		if (asyncCallback != null) {
			Map map = new HashMap();
			map.put("Latitude", gopoint.getLatitude());
			map.put("Longitude", gopoint.getLongitude());
			asyncCallback.onSuccess(map);
		}
	}

	public LatLng getINDIA() {
		return gopoint;
	}

	public void setINDIA(LatLng india) {
		gopoint = india;
	}
}
